+2007-07-09 Johan Dahlin,,, <jdahlin@lozenge>
+
+ * demos/gtk-demo/demo.ui:
+ * gtk/gtk-builder-convert:
+ * gtk/gtkactiongroup.c: (gtk_action_group_buildable_init),
+ (gtk_action_group_buildable_add_child),
+ (accelerator_start_element),
+ (gtk_action_group_buildable_custom_tag_start),
+ (gtk_action_group_buildable_custom_tag_end):
+ * gtk/gtkuimanager.c: (child_hierarchy_changed_cb),
+ (gtk_ui_manager_buildable_construct_child):
+ * tests/buildertest.c: (test_uimanager_simple):
+
+ Add actiongroup/action accelerator support for builder. #454654
+
2007-07-08 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkbuilderparser.c (pgettext): Support old-style
signals.append(child)
return signals
+def get_accelerator_nodes(node):
+ assert node.tagName == 'object'
+ accelerators = []
+ for child in node.childNodes:
+ if child.nodeType == Node.TEXT_NODE:
+ continue
+ if child.tagName == 'accelerator':
+ accelerators.append(child)
+ return accelerators
+
def get_object_node(child_node):
assert child_node.tagName == 'child'
nodes = []
group.appendChild(child)
child.appendChild(action)
+ for accelerator in get_accelerator_nodes(node):
+ signal = accelerator.getAttribute('signal')
+ if signal_name != 'activate':
+ print 'Unhandled accelerator signal for %s::%s' % (
+ node.getAttribute('class'), signal_name)
+ continue
+ accelerator.removeAttribute('signal')
+ child.appendChild(accelerator)
+
def _convert_sizegroup(self, node, prop):
# This is Gazpacho only
node.removeChild(prop)
*/
#include <config.h>
+#include <string.h>
#include "gtkactiongroup.h"
#include "gtkbuildable.h"
#include "gtkradioaction.h"
#include "gtkaccelmap.h"
#include "gtkmarshalers.h"
+#include "gtkbuilderprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
const gchar *name);
static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable);
+static gboolean gtk_action_group_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *data);
+static void gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer *user_data);
GType
gtk_action_group_get_type (void)
iface->add_child = gtk_action_group_buildable_add_child;
iface->set_name = gtk_action_group_buildable_set_name;
iface->get_name = gtk_action_group_buildable_get_name;
+ iface->custom_tag_start = gtk_action_group_buildable_custom_tag_start;
+ iface->custom_tag_end = gtk_action_group_buildable_custom_tag_end;
}
static void
GObject *child,
const gchar *type)
{
- gtk_action_group_add_action (GTK_ACTION_GROUP (buildable),
- GTK_ACTION (child));
+ gtk_action_group_add_action_with_accel (GTK_ACTION_GROUP (buildable),
+ GTK_ACTION (child), NULL);
}
static void
return self->private_data->name;
}
+typedef struct {
+ GObject *child;
+ guint key;
+ guint modifiers;
+} AcceleratorParserData;
+
+static void
+accelerator_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ gint i;
+ guint key = 0;
+ gint modifiers = 0;
+ AcceleratorParserData *parser_data = (AcceleratorParserData*)user_data;
+
+ if (strcmp (element_name, "accelerator") != 0)
+ g_warning ("Unknown <accelerator> tag: %s", element_name);
+
+ for (i = 0; names[i]; i++)
+ {
+ if (strcmp (names[i], "key") == 0)
+ key = gdk_keyval_from_name (values[i]);
+ else if (strcmp (names[i], "modifiers") == 0)
+ {
+ if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE,
+ values[i],
+ &modifiers,
+ error))
+ return;
+ }
+ }
+
+ if (key == 0)
+ {
+ g_warning ("<accelerator> requires a key attribute");
+ return;
+ }
+ parser_data->key = key;
+ parser_data->modifiers = (guint)modifiers;
+}
+
+static const GMarkupParser accelerator_parser =
+ {
+ accelerator_start_element
+ };
+
+static gboolean
+gtk_action_group_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GMarkupParser *parser,
+ gpointer *user_data)
+{
+ AcceleratorParserData *parser_data;
+
+ if (child && strcmp (tagname, "accelerator") == 0)
+ {
+ parser_data = g_slice_new0 (AcceleratorParserData);
+ parser_data->child = child;
+ *user_data = parser_data;
+ *parser = accelerator_parser;
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer *user_data)
+{
+ AcceleratorParserData *data;
+
+ if (strcmp (tagname, "accelerator") == 0)
+ {
+ GtkActionGroup *action_group;
+ GtkAction *action;
+ gchar *accel_path;
+
+ data = (AcceleratorParserData*)user_data;
+ action_group = GTK_ACTION_GROUP (buildable);
+ action = GTK_ACTION (child);
+
+ accel_path = g_strconcat ("<Actions>/",
+ action_group->private_data->name, "/",
+ gtk_action_get_name (action), NULL);
+
+ if (gtk_accel_map_lookup_entry (accel_path, NULL))
+ gtk_accel_map_change_entry (accel_path, data->key, data->modifiers, TRUE);
+ else
+ gtk_accel_map_add_entry (accel_path, data->key, data->modifiers);
+
+ gtk_action_set_accel_path (action, accel_path);
+
+ g_free (accel_path);
+ g_slice_free (AcceleratorParserData, data);
+ }
+}
+
/**
* gtk_action_group_new:
* @name: the name of the action group.
pos);
}
+static void
+child_hierarchy_changed_cb (GtkWidget *widget,
+ GtkWidget *unused,
+ GtkUIManager *uimgr)
+{
+ GtkWidget *toplevel;
+ GtkAccelGroup *group;
+ GSList *groups;
+
+ toplevel = gtk_widget_get_toplevel (widget);
+ if (!toplevel || !GTK_IS_WINDOW (toplevel))
+ return;
+
+ group = gtk_ui_manager_get_accel_group (uimgr);
+ groups = gtk_accel_groups_from_object (toplevel);
+ if (g_slist_find (groups, group) == NULL)
+ gtk_window_add_accel_group (GTK_WINDOW (toplevel), group);
+
+ g_signal_handlers_disconnect_by_func (widget,
+ child_hierarchy_changed_cb,
+ uimgr);
+}
+
static GObject *
gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
GtkBuilder *builder,
name = g_strdup_printf ("ui/%s", id);
widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name);
if (!widget)
- g_error ("Unknown ui manager child: %s\n", name);
-
+ {
+ g_error ("Unknown ui manager child: %s\n", name);
+ g_free (name);
+ return NULL;
+ }
g_free (name);
+ g_signal_connect (widget, "hierarchy-changed",
+ G_CALLBACK (child_hierarchy_changed_cb),
+ GTK_UI_MANAGER (buildable));
return G_OBJECT (widget);
}